<?php


namespace WenRuns\Laravel\Admin\Grid\Column;


use Encore\Admin\Admin;
use Encore\Admin\Grid\Model;

class RangeFilter extends \Encore\Admin\Grid\Column\RangeFilter
{
    protected $queryClosure = null;

    protected $input = null;

    const DATE_TYPE = [
        'year' => [
            'format' => 'YYYY',
            'options' => [
                1 => '一年',
                2 => '两年',
                3 => '三年',
                4 => '四年',
                5 => '五年',
            ],
            'fn' => 'function(range, end){
                var startDate;
                var endTimestamp = end.timestamp;
                switch(range){
                    case 1: // 一年
                        var startTimestamp = endTimestamp - (365 * 24 * 60 * 60);
                        startDate = new Date(startTimestamp * 1000);
                        break;
                    case 2: // 两年
                        var startTimestamp = endTimestamp - (365 * 24 * 60 * 60 * 2);
                        startDate = new Date(startTimestamp * 1000);
                        break;
                    case 3: // 三年
                        var startTimestamp = endTimestamp - (365 * 24 * 60 * 60 * 3);
                        startDate = new Date(startTimestamp * 1000);
                        break;
                    case 4: // 四年
                        var startTimestamp = endTimestamp - (365 * 24 * 60 * 60 * 4);
                        startDate = new Date(startTimestamp * 1000);
                        break;
                    case 5: // 五年
                        var startTimestamp = endTimestamp - (365 * 24 * 60 * 60 * 5);
                        startDate = new Date(startTimestamp * 1000);
                        break;
                    default:
                        return false;
                }
                return {
                    start: startDate.getFullYear(),
                    end:  end.year,
                }
            }'
        ],
        'month' => [
            'format' => 'YYYY-MM',
            'options' => [
                1 => '一月',
                2 => '三月',
                3 => '六月',
                4 => '九月',
                5 => '一年',
            ],
            'fn' => 'function(range, end){
                var startDate;
                var endTimestamp = end.timestamp;
                switch(range){
                    case 1: // 一月
                        var startTimestamp = endTimestamp - (30 * 24 * 60 * 60);
                        startDate = new Date(startTimestamp * 1000);
                        break;
                    case 2: // 三月
                        var startTimestamp = endTimestamp - (30 * 24 * 60 * 60 * 3);
                        startDate = new Date(startTimestamp * 1000);
                        break;
                    case 3: // 六月
                        var startTimestamp = endTimestamp - (30 * 24 * 60 * 60 * 6);
                        startDate = new Date(startTimestamp * 1000);
                        break;
                    case 4: // 九月
                        var startTimestamp = endTimestamp - (30 * 24 * 60 * 60 * 9);
                        startDate = new Date(startTimestamp * 1000);
                        break;
                    case 5: // 一年
                        var startTimestamp = endTimestamp - (365 * 24 * 60 * 60);
                        startDate = new Date(startTimestamp * 1000);
                        break;
                    default:
                        return false;
                }
                var sYear = startDate.getFullYear(),
                    sMonth = startDate.getMonth()+1
                return {
                    start: sYear + "-" + (sMonth < 10 ? "0" + sMonth : sMonth),
                    end:  end.year + "-" + (end.month < 10 ? "0"+end.month : end.month),
                }
            }',
        ],
        'date' => [
            'format' => 'YYYY-MM-DD',
            'options' => [
                1 => '一周',
                2 => '一月',
                3 => '二月',
                4 => '三月',
                5 => '一年',
            ],
            'fn' => 'function(range, end){
                var startDate;
                var endTimestamp = end.timestamp;
                switch(range){
                    case 1: // 一周
                        var startTimestamp = endTimestamp - (7 * 24 * 60 * 60);
                        startDate = new Date(startTimestamp * 1000);
                        break;
                    case 2: // 一月
                        var startTimestamp = endTimestamp - (30 * 24 * 60 * 60);
                        startDate = new Date(startTimestamp * 1000);
                        break;
                    case 3: // 二月
                        var startTimestamp = endTimestamp - (60 * 24 * 60 * 60);
                        startDate = new Date(startTimestamp * 1000);
                        break;
                    case 4: // 三月
                        var startTimestamp = endTimestamp - (90 * 24 * 60 * 60);
                        startDate = new Date(startTimestamp * 1000);
                        break;
                    case 5: // 一年
                        var startTimestamp = endTimestamp - (365 * 24 * 60 * 60);
                        startDate = new Date(startTimestamp * 1000);
                        break;
                    default:
                        return false;
                }
                var sh = startDate.getHours(),
                    sm = startDate.getMinutes(),
                    ss = startDate.getSeconds(),
                    sYear = startDate.getFullYear(),
                    sMonth = startDate.getMonth()+1,
                    sDay = startDate.getDate();
                return {
                    start: sYear + "-" + (sMonth < 10 ? "0" + sMonth : sMonth) + "-" + (sDay < 10 ? "0" + sDay : sDay),
                    end:  end.year + "-" + (end.month < 10 ? "0"+end.month : end.month) + "-" + (end.date < 10 ? "0"+end.date : end.date),
                }
            }',
        ],
        'time' => [
            'format' => 'HH:mm:ss',
            'options' => [
                1 => '一小时',
                2 => '三小时',
                3 => '六小时',
                4 => '半天',
                5 => '一天',
            ],
            'fn' => 'function(range, end){
                var startDate;
                var endTimestamp = end.timestamp;
                switch(range){
                    case 1: // 一小时
                        var startTimestamp = endTimestamp - (60 * 60);
                        startDate = new Date(startTimestamp * 1000);
                        break;
                    case 2: // 三小时
                        var startTimestamp = endTimestamp - (3 * 60 * 60);
                        startDate = new Date(startTimestamp * 1000);
                        break;
                    case 3: // 六小时
                        var startTimestamp = endTimestamp - (6 * 60 * 60);
                        startDate = new Date(startTimestamp * 1000);
                        break;
                    case 4: // 半天
                        var startTimestamp = endTimestamp - (12 * 60 * 60);
                        startDate = new Date(startTimestamp * 1000);
                        break;
                    case 5: // 一天
                        var startTimestamp = endTimestamp - (24 * 60 * 60);
                        startDate = new Date(startTimestamp * 1000);
                        break;
                    default:
                        return false;
                }
                var sh = startDate.getHours(),
                    sm = startDate.getMinutes(),
                    ss = startDate.getSeconds(),
                return {
                    start: (sh < 10? "0"+sh)+":"+(sm < 10?"0"+sm:sm)+":"+(ss<10?"0"+ss:ss),
                    end:  (en.hour<10?"0"+end.hour:end.hour)+":"+(end.minute<10?"0"+end.minute:end.minute)+":"+(end.second<10?"0"+end.second:end.second),
                }
            }',
        ],
        'datetime' => [
            'format' => 'YYYY-MM-DD HH:mm:ss',
            'options' => [
                1 => '一周',
                2 => '一月',
                3 => '二月',
                4 => '三月',
                5 => '一年',
            ],
            'fn' => 'function(range, end){
                var startDate;
                var endTimestamp = end.timestamp;
                switch(range){
                    case 1: // 一周
                        var startTimestamp = endTimestamp - (7 * 24 * 60 * 60);
                        startDate = new Date(startTimestamp * 1000);
                        break;
                    case 2: // 一月
                        var startTimestamp = endTimestamp - (30 * 24 * 60 * 60);
                        startDate = new Date(startTimestamp * 1000);
                        break;
                    case 3: // 二月
                        var startTimestamp = endTimestamp - (60 * 24 * 60 * 60);
                        startDate = new Date(startTimestamp * 1000);
                        break;
                    case 4: // 三月
                        var startTimestamp = endTimestamp - (90 * 24 * 60 * 60);
                        startDate = new Date(startTimestamp * 1000);
                        break;
                    case 5: // 一年
                        var startTimestamp = endTimestamp - (365 * 24 * 60 * 60);
                        startDate = new Date(startTimestamp * 1000);
                        break;
                    default:
                        return false;
                }
                var sh = startDate.getHours(),
                    sm = startDate.getMinutes(),
                    ss = startDate.getSeconds(),
                    sYear = startDate.getFullYear(),
                    sMonth = startDate.getMonth()+1,
                    sDay = startDate.getDate();
                return {
                    start: sYear + "-" + (sMonth < 10 ? "0" + sMonth : sMonth) + "-" + (sDay < 10 ? "0" + sDay : sDay),
                    end:  end.year + "-" + (end.month < 10 ? "0"+end.month : end.month) + "-" + (end.date < 10 ? "0"+end.date : end.date),
                }
            }',
        ],
    ];


    /**
     * RangeFilter constructor.
     * @param $type
     * @param null $queryClosre
     */
    public function __construct($type, $queryClosre = null)
    {
        $this->queryClosure = $queryClosre;
        parent::__construct($type);
    }

    /**
     * @param mixed $value
     * @param Model $model
     */
    public function addBinding($value, Model $model)
    {
        $value = array_filter((array)$value);

        if (empty($value)) {
            return;
        }

        $this->input = $value;
        if (is_callable($this->queryClosure)) {
            $that = $this;
            $model->where(function ($query) use ($that) {
                $that->queryClosure->call($that, $query);
            });
//            $this->queryClosure->call($this, $model);
            return $model;
        }

        $start = $value['start'] ?? null;
        $end = $value['end'] ?? null;

        if ($this->type == 'date') {
            empty($start) ?: $start = strtotime($start);
            empty($end) ?: $end = strtotime($end . ' 23:59:59');
        } elseif ($this->type == 'time') {
            $date = date('Y-m-d');
            empty($start) ?: $start = strtotime($date . ' ' . $start);
            empty($end) ?: $end = strtotime($date . ' ' . $end);
        } elseif ($this->type == 'datetime') {
            empty($start) ?: $start = strtotime($start);
            empty($end) ?: $end = strtotime($end);
        }
        if ($start) {
            $model->where($this->getColumnName(), '>=', $start);
        }
        if ($end) {
            $model->where($this->getColumnName(), '<=', $end);
        }
        return $model;
    }

    protected function addScript()
    {
        $options = [
            'locale' => config('app.locale'),
            'allowInputToggle' => true,
        ];

        if (!isset(self::DATE_TYPE[$this->type])) {
            return;
        }
        $options['format'] = self::DATE_TYPE[$this->type]['format'];
        $options = json_encode($options);
        $fn = self::DATE_TYPE[$this->type]['fn'] ?? 0;
        static $firstTime = 1;
        $script = <<<SCRIPT
$(function(){
    var h = setTimeout(function(){
        clearTimeout(h);
        $('.{$this->class['start']},.{$this->class['end']}').datetimepicker($options);
    });
    $('body').on('click', '.dropdown-menu .range-menu li',function(e) {
        var myDate = new Date();
        var endDatetime = {
            hour: myDate.getHours(),
            minute: myDate.getMinutes(),
            second: myDate.getSeconds(),
            year:  myDate.getFullYear(),
            month:  myDate.getMonth()+1,
            date: myDate.getDate(),
            timestamp: Math.round(myDate.getTime()/1000),
        };
        var range = Number(e.currentTarget.dataset.range);
        let fn = {$fn};
        if(fn){
            let value = fn(range, endDatetime);
            if(value){
                let parentEle = e.currentTarget.parentElement.parentElement;
                let endEle = parentEle.querySelector(".{$this->class['end']}");
                let startEle = parentEle.querySelector(".{$this->class['start']}");
                if(endEle){
                    endEle.value = value.end;
                }
                if(startEle){
                    startEle.value = value.start;
                }
            }
        }
    });

    if({$firstTime}){
        $('body').on("click", ".grid-table th .dropdown form a.dropdown-toggle", function(e){
            let expand = e.currentTarget.getAttribute("aria-expanded");
            if(!expand || expand == 'false'){
                let rect = e.currentTarget.getBoundingClientRect();
                let el = e.currentTarget.nextElementSibling;
                let h = setTimeout(()=>{
                    let rect1 = el.getBoundingClientRect();
                    if(rect1.left < 0){
                        let left = (Number(el.style.left.replace('px','')))-rect1.left+20;
                        el.style.left = left+'px';
                    }
                },10);
            }
        });
    }
});
SCRIPT;
        $firstTime = 0;
        Admin::script($script);
    }

    /**
     * Render this filter.
     *
     * @return string
     */
    public function render()
    {
        $script = <<<SCRIPT
$(function(){
    $('body').on('click', '.dropdown-menu input',function(e) {
        e.stopPropagation();
    });
});
SCRIPT;
        Admin::script($script);
        $this->addScript();

        $value = array_merge(['start' => '', 'end' => ''], $this->getFilterValue([]));
        $active = empty(array_filter($value)) ? '' : 'text-yellow';

        if (isset(self::DATE_TYPE[$this->type])) {
            return $this->timeRange($value, $active);
        }
        return <<<EOT
<span class="dropdown">
    <form action="{$this->getFormAction()}" pjax-container style="display: inline-block;">
        <a href="javascript:void(0);" class="dropdown-toggle {$active}" data-toggle="dropdown">
            <i class="fa fa-filter"></i>
        </a>
        <ul class="dropdown-menu" role="menu" style="padding: 10px;box-shadow: 0 2px 3px 0 rgba(0,0,0,.2);left: -70px;border-radius: 0;">
            <li style="list-style: none">
                <input type="text" class="form-control input-sm {$this->class['start']}" placeholder="最小值"  name="{$this->getColumnName()}[start]" value="{$value['start']}" autocomplete="off"/>
            </li>
            <li style="margin: 5px;list-style: none;text-align: center"></li>
            <li style="list-style: none">
                <input type="text" class="form-control input-sm {$this->class['end']}" placeholder="最大值" name="{$this->getColumnName()}[end]"  value="{$value['end']}" autocomplete="off"/>
            </li>
            <li class="divider" style="list-style: none"></li>
            <li class="text-right" style="list-style: none">
                <button class="btn btn-sm btn-primary btn-flat column-filter-submit pull-left" data-loading-text="{$this->trans('search')}..."><i class="fa fa-search"></i>&nbsp;&nbsp;{$this->trans('search')}</button>
                <span><a href="{$this->getFormAction()}" class="btn btn-sm btn-default btn-flat column-filter-all"><i class="fa fa-undo"></i></a></span>
            </li>
        </ul>
    </form>
</span>
EOT;
    }

    protected function timeRange($value, $active)
    {

        $html = '';
        $options = self::DATE_TYPE[$this->type]['options'] ?? null;
        if (!empty($options)) {
            $html = '<ul class="range-menu" role="" style="padding: 0px 10px 0px 0px; margin: 0px;width:60px;">';
            foreach ($options as $val => $text) {
                $html .= '<li style="list-style: none;cursor: pointer;text-align: right;" data-range="' . $val . '"><a>' . $text . '</a></li>';
            }
            $html .= '</ul>';
        }
        return <<<EOT
<span class="dropdown">
    <form action="{$this->getFormAction()}" pjax-container style="display: inline-block;">
        <a href="javascript:void(0);" class="dropdown-toggle {$active}" data-toggle="dropdown">
            <i class="fa fa-filter"></i>
        </a>
        <div class="dropdown-menu" role="menu" style="padding: 10px;box-shadow: 0 2px 3px 0 rgba(0,0,0,.2);left: -70px;border-radius: 0;">
            <div style="display: flex;">
                {$html}
                <ul class="" role="" style="padding: 0px;margin: 0px;min-width:80px;">
                    <li style="list-style: none">
                        <input type="text" class="form-control input-sm {$this->class['start']}" placeholder="最小值"  name="{$this->getColumnName()}[start]" value="{$value['start']}" autocomplete="off"/>
                    </li>
                    <li style="margin: 5px;list-style: none;text-align: center">至</li>
                    <li style="list-style: none">
                        <input type="text" class="form-control input-sm {$this->class['end']}" placeholder="最大值" name="{$this->getColumnName()}[end]"  value="{$value['end']}" autocomplete="off"/>
                    </li>
                </ul>

            </div>
            <div class="divider"></div>
            <div class="text-right">
                <button class="btn btn-sm btn-primary btn-flat column-filter-submit pull-left" data-loading-text="{$this->trans('search')}..."><i class="fa fa-search"></i>&nbsp;&nbsp;{$this->trans('search')}</button>
                <span><a href="{$this->getFormAction()}" class="btn btn-sm btn-default btn-flat column-filter-all"><i class="fa fa-undo"></i></a></span>
            </div>
        </div>
    </form>
</span>
EOT;
    }
}
